<template>
    <span class="f-switch" @click="isTrue = !isTrue">
        <i class="switch"></i>
        <span class="text">{{ _switch_change_styles._switch_text }}</span>
    </span>
</template>

<script setup lang="ts">
import { computed, reactive, watchEffect } from 'vue';
import type { SwitchType } from './f-switch-type';

/** 
 * 默认样式
 * defineProps 不能引用局部变量，枚举作为类型可以使用
 */
enum DEFAULT_STYLEAS {
    开关类型 = "round",
    未激活背景颜色 = "#DCDFE6",
    激活背景颜色 = "#409EFF",

    未激活文字 = "",
    激活文字 = "",
    未激活文字颜色 = "#fff",
    激活文字颜色 = "#fff",

    开关颜色 = "#fff",
    滑块宽度 = "40px",
    开关大小 = "20px"
}

const props = withDefaults(defineProps<SwitchType>(), {
    /* 开关字段 */
    type: DEFAULT_STYLEAS.开关类型,
    /** 背景 */
    inactiveColor: DEFAULT_STYLEAS.未激活背景颜色,
    activeColor: DEFAULT_STYLEAS.激活背景颜色,

    /** 文字 */
    inactiveText: DEFAULT_STYLEAS.未激活文字,
    activeText: DEFAULT_STYLEAS.激活文字,
    inactiveTextColor: DEFAULT_STYLEAS.未激活文字颜色,
    activeTextColor: DEFAULT_STYLEAS.激活文字颜色,

    /** 开关颜色 */
    switchColor: DEFAULT_STYLEAS.开关颜色,
    /** 滑块宽度 */
    switchWidth: DEFAULT_STYLEAS.滑块宽度,
    /** 开关大小 */
    switchSize: DEFAULT_STYLEAS.开关大小
})

/**
 * 样式转换为 px
 * @param val 宽度大小
 */
function _Typeof_ToStr(val: string | number) {
    let newVal = val
    if (typeof val == "number" || !isNaN(Number(val))) {
        newVal += "px"
    }
    return newVal
}

/** 开关滑块宽度和大小 */
const _switch_styles = computed(() => {
    let width = _Typeof_ToStr(props.switchWidth)
    let size = _Typeof_ToStr(props.switchSize)

    return {
        width, size
    }
})

/** 开关状态 */
const isTrue = defineModel<boolean>()

/** 开关状态改变使用样式 */
const _switch_change_styles = reactive({
    /* 开关 */
    _switch_transform: "",  // 动画
    _switch_bgColor: "",    // 背景
    _switch_color: props.switchColor,   // 颜色
    _switch_width: _switch_styles.value.width,    // 滑块宽度
    _switch_size: _switch_styles.value.size,   // 大小
    _switch_radius: props.type === "square" ? ((parseInt(_switch_styles.value.size + '') / 10) || 1) + "px" : _switch_styles.value.size, // 圆角

    /* 文字 */
    _switch_text_move: "",  // 动画
    _switch_text: "",   // 描述
    _text_color: "",   // 文字颜色
})

// 居中内距，使文字描述居中
const _center_padding = `${((parseInt(_switch_styles.value.size + "") || 0) / 5) * 2}px`

watchEffect(() => {
    // 滑块动画
    _switch_change_styles._switch_transform = `translateX(${isTrue.value ? 100 : 0}%)`
    // 滑块背景
    _switch_change_styles._switch_bgColor = `${isTrue.value ? props.activeColor : props.inactiveColor}`
    // 描述文字
    _switch_change_styles._switch_text = `${isTrue.value ? props.activeText : props.inactiveText}`
    // 文字切换动画
    _switch_change_styles._switch_text_move = `0 ${isTrue.value ? _switch_change_styles._switch_size : _center_padding} 0 ${!isTrue.value ? _switch_change_styles._switch_size : _center_padding}`
    // 文字颜色
    _switch_change_styles._text_color = `${isTrue.value ? props.activeTextColor : props.inactiveTextColor}`
})

</script>

<style lang="scss" scoped>
// 滑块宽度
$width: v-bind("_switch_change_styles._switch_width");
// 动画时间
$transition_time: 300ms;
// 开关大小
$switch_size: v-bind("_switch_change_styles._switch_size");
// 开关圆角
$border_radius: v-bind("_switch_change_styles._switch_radius");

.f-switch {
    display: inline-block;
    box-sizing: border-box;
    position: relative;
    min-width: $width;
    height: $switch_size;
    overflow: hidden;
    cursor: pointer;
    color: #fff;
    border-radius: $border_radius;
    background-color: v-bind("_switch_change_styles._switch_bgColor");
    transition: background-color $transition_time;

    &+& {
        margin-left: 15px;
    }

    /* 开关滑块 */
    .switch {
        position: absolute;
        display: inline-block;
        /* 减去开关大小 */
        width: calc(100% - $switch_size);
        height: 100%;
        transform: v-bind("_switch_change_styles._switch_transform");
        transition: transform $transition_time;

        /** 开关 */
        &::before {
            position: absolute;
            display: inline-block;
            content: "";
            width: $switch_size;
            height: 100%;
            transform: scale(.8);
            border-radius: $border_radius;
            background-color: v-bind("_switch_change_styles._switch_color");
        }
    }

    /** 文字 */
    .text {
        box-sizing: border-box;
        display: flex;
        justify-content: center;
        height: $switch_size;
        align-items: center;
        user-select: none;
        /* 动态修改文字大小 */
        font-size: calc($switch_size * (3 / 5));
        color: v-bind("_switch_change_styles._text_color");
        padding: v-bind("_switch_change_styles._switch_text_move");
        transition: padding $transition_time, color $transition_time;
    }
}
</style>